%数据初始化显示
%CP矩阵用于NURBS曲面拟合  data矩阵里数据用于 更新坐标
%主要就是
%%%%%%%%%%%%%%
%1、CP - data矩阵的替换
%%%%%%%%%%%%%%
%2、判断鼠标处于哪一个子界面：利用鼠标位置/总窗口宽高；确定鼠标位置的比例
%   结合子窗口位于总窗口的位置比例 进行确定
%%%%%%%%%%%%%%
%3、 判断选中哪个点： 在任意一个投影子界面上选中一个点，得到该点在data矩阵里的位置；
%   利用此位置找到data里面该点的xyz坐标，后续更新都利用这个位置来操作。
global CP m n
CP=[[0,0,0] [0,1,0] [0,2,0] [0,3,0] [0,4,0]   [0,5,0]
    [1,0,0] [1,1,1] [1,2,1] [1,3,1] [1,4,0.2] [1,5,0]
    [2,0,0] [2,1,1] [2,2,2] [2,3,1] [2,4,0.5] [2,5,0]
    [3,0,0] [3,1,1] [3,2,1] [3,3,1] [3,4 0.2] [3,5,0]
    [4,0,0] [4,1,0] [4,2,0] [4,3,0] [4,4,0]   [4,5,0]
    ];
[m,n]=size(CP);%向量格式存储的数据的行列
data = []; %将向量格式控制点数据转变格式 便于更新点坐标
%data数据格式：每一行是一个点；总共三列代表x y z三分量
for i = 1:m
    for j = 1:3:n-2
        data = [data; CP(i, j:j+2)];
    end
end
%鼠标移动函数调用
MouseControl(figure(1), data);

function MouseControl(gcf, data)
    global fig_width fig_height%窗口宽高 用于计算鼠标处于哪个窗口
    global mouseSign dataLabel mousePoint 
    %mouseSign 鼠标标值  0释放 1单击左键
    %dataLabel 选中哪个点的标志  选中该点对应的行设为1，否则为0
    %mousePoint 鼠标的坐标
    global figIndex minIndex %鼠标在哪个窗口标值； 选中的哪个点标值
    global fig_3 fig_2xy fig_2xz fig_2yz %三维图 xy投影，xz投影，yz投影的画图句柄
    figIndex = 0;
    minIndex = 0;
    
    dataLabel = zeros(size(data,1),1);
    show(data, dataLabel);
    mouseSign = 0;
    set(gcf,'WindowButtonMotionFcn',@ButtonMotionFcn,...
    'WindowButtonDownFcn',@ButttonDownFcn,'WindowButtonUpFcn',@ButttonUpFcn);
    function ButtonMotionFcn(~,~)
        set(gcf,'Pointer','hand'); % 设置为手的形状
        fig_pos = get(gcf,'Position');
        fig_width = fig_pos(3);
        fig_height = fig_pos(4);
        
        %更新数据 进入标志 鼠标未释放 即鼠标移动且单击左键时候
        if mouseSign~=0
            switch figIndex
                %2 3 4分别代表鼠标处于xy投影，xz投影，yz投影对应的图
                case 2
                    if minIndex~=0
                        mousePoint = get(fig_2xy, 'CurrentPoint');
                        data(minIndex,1) = mousePoint(1,1);
                        data(minIndex,2) = mousePoint(1,2);
                    end
                case 3
                    if minIndex~=0
                        mousePoint = get(fig_2yz, 'CurrentPoint');
                        data(minIndex,2) = mousePoint(1,1);
                        data(minIndex,3) = mousePoint(1,2);
                    end
                case 4
                    if minIndex~=0
                        mousePoint = get(fig_2xz, 'CurrentPoint');
                        data(minIndex,1) = mousePoint(1,1);
                        data(minIndex,3) = mousePoint(1,2);
                    end
            end  
            %更新显示函数  
            show(data, minIndex)   
        end
    end
    function ButttonDownFcn(~,~)
        switch(get(gcf,'SelectionType'))
            case 'normal'
                mouseSign = 1;
                str = '单机左键';
                mousePoint_inFig = get(gcf,'CurrentPoint');%获取在整个图像中鼠标位置 绝对的数值
                %计算百分比 ，确定鼠标位于哪个窗口（每个子图在整个图像中位置是百分比确定的）
                figIndex = getFigChildIndex(mousePoint_inFig(1)/fig_width, mousePoint_inFig(2)/fig_height);   
                %得到鼠标选中的 点(依靠距离判断 取最小距离且小于阈值)
                minIndex = getMinIndex(figIndex,data,1);
            case 'alt'
                str = '单机右键/ctrl+左';
                mouseSign = 2;                 
            case 'open'
                str = '双击任意键'; 
            otherwise
                str = '其他';
        end
        disp(str);
    end
    function ButttonUpFcn(~,~)
        mouseSign = 0;
        disp('鼠标释放')
    end
end
function index = getFigChildIndex(x, y)
    %判断鼠标属于哪一个图上面； 都没在则返回0
    global fig_3 fig_2xy fig_2xz fig_2yz
    index = 0;
    %x y fig_3_pos这些都是按比例存储的
    fig_3_pos = get(fig_3,'Position');
    fig_2xy_pos = get(fig_2xy,'Position');
    fig_2yz_pos = get(fig_2yz,'Position');
    fig_2xz_pos = get(fig_2xz,'Position');
    if((x>fig_3_pos(1)) && (x<fig_3_pos(1)+fig_3_pos(3)))  
        if ((y>fig_3_pos(2)) && (y<fig_3_pos(2)+fig_3_pos(4)))
            index = 1;
        end
    end
    if((x>fig_2xy_pos(1)) && (x<fig_2xy_pos(1)+fig_2xy_pos(3)))
        if ((y>fig_2xy_pos(2)) && (y<fig_2xy_pos(2)+fig_2xy_pos(4)))
            index = 2;
        end
    end
    if((x>fig_2yz_pos(1)) && (x<fig_2yz_pos(1)+fig_2yz_pos(3)))
        if ((y>fig_2yz_pos(2)) && (y<fig_2yz_pos(2)+fig_2yz_pos(4)))
            index = 3;
        end
    end
    if((x>fig_2xz_pos(1)) && (x<fig_2xz_pos(1)+fig_2xz_pos(3)))
        if ((y>fig_2xz_pos(2)) && (y<fig_2xz_pos(2)+fig_2xz_pos(4)))
            index = 4;
        end
    end
end
function index = getMinIndex(figIndex,data, minVal)
    %确定鼠标选中的点  因为不同投影图像里找到的坐标是不一样xy，xz，yz
    %但选中的点的序号是一样的，采用这个序号去找到其他图像里的对应点
    index = 0;
    mousePoint = get(gca, 'CurrentPoint');
    dis = zeros(size(data,1), 1);
    switch figIndex
        case 2
            newdata = [data(:,1),data(:,2)];
            for i = 1:size(data,1)
                dis(i) = norm(mousePoint(1,1:2) - newdata(i,:));
            end
            [val, row] = min(dis);
            if val<minVal
                index = row;
            end
        case 3
            newdata = [data(:,2),data(:,3)];
            for i = 1:size(data,1)
                dis(i) = norm(mousePoint(1,1:2) - newdata(i,:));
            end
            [val, row] = min(dis);
            if val<minVal
                index = row;
            end
        case 4
            newdata = [data(:,1),data(:,3)];
            for i = 1:size(data,1)
                dis(i) = norm(mousePoint(1,1:2) - newdata(i,:));
            end
            [val, row] = min(dis);
            if val<minVal
                index = row;
            end
    end  
end
function show(data, minIndex)
    %显示函数  通过minIndex将选中的点 进行特殊显示
    %同时将data数据格式转换未CP数据格式，因为画三维曲面用的是CP格式
    global fig_3 fig_2xy fig_2xz fig_2yz CP m n
    fig_3 = subplot(2,2,1);
    hold off;
    scatter3(data(:,1), data(:,2), data(:,3), 'ro');
    %显示 转换未CP格式
    CP = [];
    num = 1;
    for i = 1:m
        for j = 1:3:n-2
            CP(i, j:j+2) = data(num,:);
            num = num +1;
        end
    end
    %调用曲面拟合算法
    [S ,CPx, CPy, CPz] =  NURBS_surface(CP);
    %画三维曲面图
    x=reshape(S(:,1),101,101);
    y=reshape(S(:,2),101,101);
    z=reshape(S(:,3),101,101);
    surf(x,y,z)
    hold on
    mesh(CPx,CPy,CPz)
    hidden off
    xlabel('x'),ylabel('y'),zlabel('z')
    grid on
    axis image
    axis vis3d
    hold on;
    
    plot3(data(:,1), data(:,2), data(:,3));
    hold on;
    if (minIndex ~= 0)
        scatter3(data(minIndex,1), data(minIndex,2), data(minIndex,3), 'r*');
    end
    axis([-1,5,-1,5,0,2]);
    title("三维图");
    %%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%
    fig_2xy = subplot(2,2,2);
    hold off;
    scatter(data(:,1), data(:,2), 'bo');
    hold on;
    plot(data(:,1), data(:,2));
    hold on;
    if (minIndex ~= 0)
        scatter(data(minIndex,1), data(minIndex,2), 'b*');
    end
    axis([0,6,0,6]);
    title("二维图-xy面投影");
    %%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%
    fig_2yz = subplot(2,2,3);
    hold off;
    scatter(data(:,2), data(:,3), 'bo');
    hold on;
    plot(data(:,2), data(:,3));
    hold on;
    if (minIndex ~= 0)
        scatter(data(minIndex,2), data(minIndex,3), 'b*');
    end
    axis([0,6,0,6]);
    title("二维图-yz面投影");
    %%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%
    fig_2xz = subplot(2,2,4);
    hold off;
    scatter(data(:,1), data(:,3), 'bo');
    hold on;
    plot(data(:,1), data(:,3));
    hold on;
    if (minIndex ~= 0)
        scatter(data(minIndex,1), data(minIndex,3), 'b*');
    end
    axis([0,6,0,6]);
    title("二维图-xz面投影");
end



